package com.digitaldreamers.framework.scene;

import org.andengine.engine.Engine;
import org.andengine.engine.camera.hud.HUD;
import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.entity.scene.Scene;

import com.digitaldreamers.framework.BaseResourceManager;
import com.digitaldreamers.framework.scene.layer.ManagedLayer;
public class SceneManager {
	private static Object lockObj = new Object();
	private static SceneManager instance;
	
	public ManagedScene mCurrentScene;
	public ManagedLayer mCurrentLayer;
	public boolean mIsLayerShown;
	protected int mNumFamesPassed;
	protected boolean mLoadingSceneHandlerRegistered;
	protected boolean mCameraHadHud;
	protected ManagedScene mNextScene;
	protected Engine mEngine;
	protected Scene mPlaceholderModalScene;
	protected BaseResourceManager mBaseResourceManager;
	private IUpdateHandler mLoadingSceneHandler;
	
	private SceneManager() {
		mNumFamesPassed = -1;
		mLoadingSceneHandlerRegistered = false;
		mCameraHadHud = false;
		mIsLayerShown = false;
		mBaseResourceManager = BaseResourceManager.getInstance();
		mEngine = mBaseResourceManager.mEngine;
		mLoadingSceneHandler = new IUpdateHandler() {
			@Override
			public void onUpdate(float pSecondsElapsed) {
				mNumFamesPassed++;
				mNextScene.mElapsedLoadingScreneTime += pSecondsElapsed;
				if(mNumFamesPassed == 1) {
					if(mCurrentScene!=null) {
						mCurrentScene.onHideManagedScene();
						mCurrentScene.onUnloadManagedScene();
					}
					mNextScene.onLoadManagedScene();
				}
				
				if(mNumFamesPassed > 1 &&
						mNextScene.mElapsedLoadingScreneTime >= mNextScene.mMinLoadingSceneTime &&
						mNextScene.mIsLoaded) {
					mNextScene.clearChildScene();
					mNextScene.onLoadingSceneUnloadAndHidden();
					mNextScene.onShowManagedScene();
					mCurrentScene = mNextScene;
					mNextScene.mElapsedLoadingScreneTime = 0f;
					mNumFamesPassed = -1;
					mEngine.unregisterUpdateHandler(this);
					mLoadingSceneHandlerRegistered = false;
				}
			}
			
			@Override public void reset() {
				
			}
		};
	}
	
	public static SceneManager getInstance() {
		if(instance == null) {
			synchronized(lockObj) {
				if(instance == null) {
					instance = new SceneManager();
				}
			}
		}
		return instance;
	}
	
	public void showScene(final ManagedScene pManagedScene) {
		mEngine.getCamera().set(0, 0, mBaseResourceManager.mCameraWidth, mBaseResourceManager.mCameraHeight);
		if(pManagedScene.mHasLoadingScene) {
			pManagedScene.setChildScene(pManagedScene.onLoadingSceneLoadAndShown(), true, true, true);
			if(mLoadingSceneHandlerRegistered) {
				mNumFamesPassed = -1;
				mNextScene.clearChildScene();
				mNextScene.onLoadingSceneUnloadAndHidden();
			} else {
				mEngine.registerUpdateHandler(mLoadingSceneHandler);
				mLoadingSceneHandlerRegistered = true;
			}
			mNextScene = pManagedScene;
			mEngine.setScene(pManagedScene);
			return;
		}
		
		mNextScene = pManagedScene;
		mEngine.setScene(mNextScene);
		if(mCurrentScene != null) {
			mCurrentScene.onHideManagedScene();
			mCurrentScene.onUnloadManagedScene();
		}
		mNextScene.onLoadManagedScene();
		mNextScene.onShowManagedScene();
		mCurrentScene = mNextScene;
	}
	
	public void showLayer(final ManagedLayer pLayer, final boolean pIsSuspendSceneDrawing, final boolean pIsSuspendSceneUpdates, final boolean pIsSuspendSceneTouchEvents) {
		if(mEngine.getCamera().hasHUD()) {
			mCameraHadHud = true;
		} else {
			mCameraHadHud = false;
			HUD placeholderHud = new HUD();
			mEngine.getCamera().setHUD(placeholderHud);
		}
		if(pIsSuspendSceneDrawing || pIsSuspendSceneUpdates || pIsSuspendSceneTouchEvents) {
			mEngine.getCamera().getHUD().setChildScene(pLayer, pIsSuspendSceneDrawing, pIsSuspendSceneUpdates, pIsSuspendSceneTouchEvents);
			mEngine.getCamera().getHUD().setOnSceneTouchListenerBindingOnActionDownEnabled(true);
			if(mPlaceholderModalScene == null) {
				mPlaceholderModalScene = new Scene();
				mPlaceholderModalScene.setBackgroundEnabled(false);
			}
			mCurrentScene.setChildScene(mPlaceholderModalScene, pIsSuspendSceneDrawing, pIsSuspendSceneUpdates, pIsSuspendSceneTouchEvents);
		} else {
			mEngine.getCamera().getHUD().setChildScene(pLayer);
		}
		pLayer.setCamera(mEngine.getCamera());
		pLayer.onShowManagedLayer();
		mIsLayerShown = true;
		mCurrentLayer = pLayer;
	}
	
	public void hideLayer() {
		if(mIsLayerShown) {
			mEngine.getCamera().getHUD().clearChildScene();
			if(mCurrentScene.hasChildScene()) {
				if(mCurrentScene.getChildScene() == mPlaceholderModalScene) {
					mCurrentScene.clearChildScene();
				}
			}
			if(!mCameraHadHud) {
				mEngine.getCamera().setHUD(null);
			}
			mIsLayerShown = false;
			mCurrentLayer = null;
		}
	}
}